package haierhome.krund.cn.daggertworetrofitrxjavamvp.rxjava.exampleone;

import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import haierhome.krund.cn.daggertworetrofitrxjavamvp.R;
import haierhome.krund.cn.daggertworetrofitrxjavamvp.rxjava.exampleone.bean.Student;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * https://gank.io/post/560e15be2dca930e00da1083#toc_1
 * 该片博客详细讲解了RxJava
 * Rxjava基本运用
 */

public class RxJavaActivity extends AppCompatActivity {

    private String tag = "RxJavaActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rx_java);

        partSix();

    }

    //观察者 被观察者 之间关系
    public void partOne() {
        /**
         * 第一步创建观察者
         */

        //创建Observer创建观察者
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onCompleted() {
                Log.d(tag, "Item: " + "complete");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(tag, "Completed!");
            }

            @Override
            public void onNext(String s) {
                Log.d(tag, "Item: " + s);
            }
        };
        //该抽象类对Observer进行了一些扩展
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onNext(String s) {
                Log.d(tag, "Item: " + s);
            }

            @Override
            public void onCompleted() {
                Log.d(tag, "Completed!");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(tag, "Error!");
            }
        };

        /**
         * 第二步 创建Observerable被观察者
         */
        Observable observable = Observable.create(new Observable.OnSubscribe<String>() {

            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("Hello");
                subscriber.onNext("Hi");
                subscriber.onNext("Aloha");
                subscriber.onCompleted();
            }
        });
        /**
         * 以下这两种方式同上面 是一种省略的写法
         */
//        Observable observable = Observable.just("Hello", "Hi", "Aloha");

//        String[] words = {"Hello", "Hi", "Aloha"};
//        Observable observable = Observable.from(words);
        /**
         * 第三部 被观察者设置监听
         *
         * 有人可能会注意到， subscribe() 这个方法有点怪：它看起来是『observalbe 订阅了
         * observer / subscriber』而不是『observer / subscriber 订阅了 observalbe』，
         * 这看起来就像『杂志订阅了读者』一样颠倒了对象关系。这让人读起来有点别扭，
         * 不过如果把 API 设计成 observer.subscribe(observable) / subscriber.subscribe(observable) ，
         * 虽然更加符合思维逻辑，但对流式 API 的设计就造成影响了，比较起来明显是得不偿失的。
         *
         * 所以还是被订阅者订阅订阅者
         */
        //observable.subscribe(subscriber);


        /**
         * 除了 subscribe(Observer) 和 subscribe(Subscriber) ，subscribe()
         * 还支持不完整定义的回调，RxJava 会自动根据定义创建出 Subscriber 。形式如下：
         */
        Action1<String> onNextAction = new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(tag, "s");
            }
        };
        Action1<Throwable> onErrorAction = new Action1<Throwable>() {
            // onError()
            @Override
            public void call(Throwable throwable) {
                // Error handling
            }
        };
        Action0 onCompletedAction = new Action0() {
            // onCompleted()
            @Override
            public void call() {
                Log.d(tag, "completed");
            }
        };

// 自动创建 Subscriber ，并使用 onNextAction 来定义 onNext()
//        observable.subscribe(onNextAction);
// 自动创建 Subscriber ，并使用 onNextAction 和 onErrorAction 来定义 onNext() 和 onError()
//        observable.subscribe(onNextAction, onErrorAction);
// 自动创建 Subscriber ，并使用 onNextAction、 onErrorAction 和 onCompletedAction 来定义 onNext()、 onError() 和 onCompleted()
//        observable.subscribe(onNextAction, onErrorAction, onCompletedAction);
    }

    public void partTwo() {
        /**
         * 例一  遍历names中所有字符串
         */
        String[] names = {"小兰", "小张", "小王", "小丽"};
        Observable.from(names)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String name) {
                        Log.d(tag, name);
                    }
                });
        /**
         * 例二
         * 由 id 取得图片并显示
         */
        final int drawableRes = R.drawable.ic_launcher;
        final ImageView imageView = (ImageView) findViewById(R.id.iv_show);
        Observable.create(new Observable.OnSubscribe<Drawable>() {
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void call(Subscriber<? super Drawable> subscriber) {
                Drawable drawable = getTheme().getDrawable(drawableRes);
                subscriber.onNext(drawable);
                subscriber.onCompleted();
            }
        }).subscribe(new Observer<Drawable>() {
            @Override
            public void onNext(Drawable drawable) {
                imageView.setImageDrawable(drawable);
            }

            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
                Toast.makeText(RxJavaActivity.this, "Error!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 第三部分 线程切换
     */
    public void partThree() {
        /**
         * 例一
         */
        Observable.just(1, 2, 3, 4)
                .subscribeOn(Schedulers.io())              // 指定 subscribe() 发生在 IO 线程  onnext onerror
                .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程  回调就是call方法
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer number) {
                        Log.d(tag, "number:" + number);
                        Log.i(tag, Thread.currentThread().getName());
                    }
                });
    }

    //路径转换bitmap
    public Bitmap getBitmapFromPath(String filepath) {
        return null;
    }

    //展示bitmap
    public void showBitmap(Bitmap bitmap) {
    }

    /**
     * 变换 重点内容
     */

    public void partFour() {
//       例一 map变换
//      这里出现了一个叫做 Func1 的类。它和 Action1 非常相似，也是 RxJava 的一个接口，
//      用于包装含有一个参数的方法。 Func1 和 Action 的区别在于， Func1 包装的是有返回值的方法。
//      另外，和 ActionX 一样， FuncX 也有多个，用于不同参数个数的方法。FuncX 和 ActionX 的区别在 FuncX 包装的是有返回值的方法。
//        Observable.just("images/logo.png") // 输入类型 String
//                .map(new Func1<String, Bitmap>() {
//                    @Override
//                    public Bitmap call(String filePath) { // 参数类型 String
//                        return getBitmapFromPath(filePath); // 返回类型 Bitmap
//                    }
//                })
//                .subscribe(new Action1<Bitmap>() {
//                    @Override
//                    public void call(Bitmap bitmap) { // 参数类型 Bitmap
//                        showBitmap(bitmap);
//                    }
//                });

//        例二 flatmap变换

        //创建课程
        Student.Course math = new Student.Course("math");
        Student.Course english = new Student.Course("english");
        Student.Course chinese = new Student.Course("chinese");

        //创建学生
        final Student studen1 = new Student("张三");
        ArrayList<Student.Course> list1 = new ArrayList<>();
        list1.add(math);
        list1.add(english);
        studen1.setList_course(list1);


        Student studen2 = new Student("李四");
        ArrayList<Student.Course> list2 = new ArrayList<>();
        list2.add(math);
        list2.add(chinese);
        studen2.setList_course(list2);


        Student studen3 = new Student("王五");
        ArrayList<Student.Course> list3 = new ArrayList<>();
        list3.add(math);
        list3.add(chinese);
        studen3.setList_course(list3);


        Student studen4 = new Student("赵六");
        ArrayList<Student.Course> list4 = new ArrayList<>();
        list4.add(math);
        list4.add(chinese);
        studen4.setList_course(list4);

        //学生数组
        Student[] students = {studen1, studen2, studen3, studen4};

        //观察者
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String name) {
                Log.d(tag, name);
            }
        };
        //打印所有学生的课程名
        Subscriber<Student> subscriberCourse = new Subscriber<Student>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Student student) {
                List<Student.Course> courses = student.getList_course();
                for (int i = 0; i < courses.size(); i++) {
                    Student.Course course = courses.get(i);
                    Log.d(tag, course.getName());
                }
            }
        };
        //被观察者  数据传入
        Observable.from(students)
                .map(new Func1<Student, Student>() {
                    @Override
                    public Student call(Student student) {
                        return student;
                    }
                })
                .subscribe(subscriberCourse);

//        Observable.create(new Observable.OnSubscribe<Object>() {
//            @Override
//            public void call(Subscriber<? super Object> subscriber) {
//
//            }
//        });
    }

    /**
     * 变换flatMap
     * 从上面的代码可以看出， flatMap() 和 map() 有一个相同点：它也是把传入的参数转化之后返回另一个对象。
     * 但需要注意，和 map() 不同的是， flatMap() 中返回的是个 Observable 对象，并且这个 Observable 对象并不是被直接发送到了
     * Subscriber 的回调方法中。 flatMap() 的原理是这样的：1. 使用传入的事件对象创建一个 Observable 对象；2. 并不发送这个 Observable,
     * 而是将它激活，于是它开始发送事件；3. 每一个创建出来的 Observable 发送的事件，都被汇入同一个 Observable ，
     * 而这个 Observable 负责将这些事件统一交给 Subscriber 的回调方法。这三个步骤，把事件拆成了两级，通过一组新创建的 Observable
     * 将初始的对象『铺平』之后通过统一路径分发了下去。而这个『铺平』就是 flatMap() 所谓的 flat。
     */
    public void partFive() {
        //创建课程
        Student.Course math = new Student.Course("math");
        Student.Course english = new Student.Course("english");
        Student.Course chinese = new Student.Course("chinese");

        //创建学生
        final Student studen1 = new Student("张三");
        ArrayList<Student.Course> list1 = new ArrayList<>();
        list1.add(math);
        list1.add(english);
        studen1.setList_course(list1);


        Student studen2 = new Student("李四");
        ArrayList<Student.Course> list2 = new ArrayList<>();
        list2.add(math);
        list2.add(chinese);
        studen2.setList_course(list2);


        Student studen3 = new Student("王五");
        ArrayList<Student.Course> list3 = new ArrayList<>();
        list3.add(math);
        list3.add(chinese);
        studen3.setList_course(list3);


        Student studen4 = new Student("赵六");
        ArrayList<Student.Course> list4 = new ArrayList<>();
        list4.add(math);
        list4.add(chinese);
        studen4.setList_course(list4);

        //学生数组
        Student[] students = {studen1, studen2, studen3, studen4};

        Subscriber<Student.Course> subscriber = new Subscriber<Student.Course>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Student.Course course) {
                Log.d(tag, course.getName());
            }
        };
        Observable.from(students).flatMap(new Func1<Student, Observable<Student.Course>>() {
            @Override
            public Observable<Student.Course> call(Student student) {
                return Observable.from(student.getList_course());
            }
        }).subscribe(subscriber);
    }

    <T> Observable.Transformer<T, T> applySchedulers() {
        return observable -> observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public void partSix() {

        //compose 得到一个observable设定好线程的observale的被观察者。

        //创建课程
        Student.Course math = new Student.Course("math");
        Student.Course english = new Student.Course("english");
        Student.Course chinese = new Student.Course("chinese");

        //创建学生
        final Student studen1 = new Student("张三");
        ArrayList<Student.Course> list1 = new ArrayList<>();
        list1.add(math);
        list1.add(english);
        studen1.setList_course(list1);


        Student studen2 = new Student("李四");
        ArrayList<Student.Course> list2 = new ArrayList<>();
        list2.add(math);
        list2.add(chinese);
        studen2.setList_course(list2);


        Student studen3 = new Student("王五");
        ArrayList<Student.Course> list3 = new ArrayList<>();
        list3.add(math);
        list3.add(chinese);
        studen3.setList_course(list3);


        Student studen4 = new Student("赵六");
        ArrayList<Student.Course> list4 = new ArrayList<>();
        list4.add(math);
        list4.add(chinese);
        studen4.setList_course(list4);

        //学生数组
        Student[] students = {studen1, studen2, studen3, studen4};

        Observable.create(new Observable.OnSubscribe<Student>() {
            @Override
            public void call(Subscriber<? super Student> subscriber) {
                for (int i = 0; i < students.length; i++) {
                    Log.i("@@", Thread.currentThread().getName());
                    subscriber.onNext(students[i]);
                }
            }
        }).compose(applySchedulers()).
                map(new Func1<Student, String>() {
            @Override
            public String call(Student student) {
                return null;
            }
        }).subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread()).
                subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String studentName) {
                        Log.i("@@", "--" + studentName);
                        Log.i("@@", "--" + Thread.currentThread().getName());
                    }
                });



    }
}
